package main

import (
	"flag"
	"math"
	"time"

	"gitee.com/thubcc/mobile/lte"
	"gitee.com/thubcc/rtlmmap"
	"github.com/prometheus/common/log"
)

var (
	argPort  = flag.Int("p", 0, "Rx antana port")
	argFc    = flag.Float64("f", 874.2e6, "LTE Center Freqency")
	argGain  = flag.Float64("g", 40.0, "Rx Gain")
	argAFC   = flag.Bool("a", false, "Do AFC")
	argReset = flag.Bool("r", false, "Reset PPM")
)

func afcInit(view *rtlmmap.View) (rsBest *lte.ScanRefResult) {
	ftco := view.GetFTco()
	if *argReset {
		ftco.ResetPPM()
	} else {
		ftco.InitPPM()
	}
	view.HardReset()
	step := true
	for step {
		view.Reset()
		rfd := view.Raw(0, 100)
		df, amp, t, pos := lte.ScanPssAll.SearchPSS(rfd, 874.2e6)
		log.Info("Searching ", df, amp, t, pos)
		if math.Abs(df) < 3e3 {
			log.Info("AFC Step 1 ready")
			rs := lte.ScanRefSym(rfd, t, 0, pos)
			df = rs[0].Df
			log.Info(rs[0].Amp, rs[0].Cid, rs[0].Pos, rs[0].Df)
			rsBest = rs[0]
			step = false
		}
		log.Info("Set df:", df)
		ftco.PPMF(df)
	}
	log.Info("AFC Step 2 ready")
	return
}

func afc(do_one chan struct{}) {
	view := rtlmmap.NewRtlView(*argPort, rtlmmap.DefaultLTEConfig)
	ftco := view.GetFTco()
	init := false
	var rsBest *lte.ScanRefResult
	rs := lte.NewPeakRecords(8)
	for true {
		if !init {
			rsBest = afcInit(view)
			view.Reset()
			rfd := view.Raw(0, 100)
			pos, _ := lte.RefSignalPeak(rfd, rsBest.Cid, 0)
			rs.Init(lte.NewPeakRecord(pos))
			init = true
		}
		<-do_one
		view.Reset()
		rfd := view.Raw(0, 100)
		pos, amp := lte.RefSignalPeak(rfd, rsBest.Cid, 0)
		df := lte.AFCSoltofCell(rfd, rsBest.Cid, 0, pos)
		log.Infof("id:%4d@%06d, amp:%08.0f, df:%06.2f", rsBest.Cid, pos, amp, df)
		ftco.PPMF(df / 2.)
		rs.Add(lte.NewPeakRecord(pos))
		if stdpos, ok := rs.IsSynced(); !ok {
			init = false
			log.Info("AFC need reset ", stdpos)
		}
	}
}

func main() {
	flag.Parse()

	var dev = rtlmmap.NewDevice(*argPort)
	dev.Open()
	dev.Start()
	dev.SetFrequency(int(*argFc))
	dev.SetSampleRate(1920000)
	dev.SetGain(int(*argGain * 10.))
	var do_one = make(chan struct{}, 1)
	if *argAFC {
		go afc(do_one)
	}
	i := 0
	for true {
		time.Sleep(time.Second * 5)
		if *argAFC {
			do_one <- struct{}{}
		}
		i += 1
	}
}
